package CRESTAURANT;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.text.ParseException;
import java.sql.PreparedStatement;

 
/**
 * PRA 1 - Ex 2.
 * Class to insert working shifts (composition) to the database.
 */
public class CompositionInsertion {

	private static final int PK_ERROR = -268;
	private static final int FK_ERROR = -691;
	private static final int RULE_ERROR = -746;
	

	private static final String CONSTRAINT_FK_INGREDIENT       = "fk_ingredients";
	private static final String CONSTRAINT_FK_RECEIPT          = "fk_receipts";	
	
	/**
	 * Default constructor.
	 */
	public CompositionInsertion() {
	}

	
	/**
 	 * Commits the current transaction. Any error occurred is ignored.
	 * @param con DB connection
	 */
	private void commit(Connection con) {
		try {
			con.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Roll backs the current transaction. Any error occurred is ignored.
	 * @param con DB Connection
	 */
	private void rollback(Connection con) {
		try {
			con.rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	 * Method to get working shifts (incorporations) data from a file
	 * @return List of shifts to be incorporated to the fair database
	 * @throws FileNotFoundException File with the data not found
	 * @throws IOException There was a problem reading the data file
	 * @throws ParseException Error parsing the date
	 */
	
	public List<Composition> getCompositionData ()
		throws FileNotFoundException, IOException, ParseException {

		String file = "composition.txt";
		List<Composition> incList = new ArrayList<Composition>(); 
		
		List<String> data = Utilities.readFile(file, ";");
		Iterator<String> list = data.iterator();
		while (list.hasNext()) {
			Composition com = new Composition();
			
			// It's assumed that the file has a correct format, otherwise
			// we should check the list is not empty			
			com.setReceiptCode(new Integer(list.next()));
			com.setIngredientCode(new Integer(list.next()));
			String s= list.next();
			com.setQuantity(new Double(s));
		
			incList.add(com);
		}
		return incList;
	}

	/**
	 * Inserts a list of working shifts (Compositions) to the database
	 * @param con Database connection
	 * @param lIncorporate List of working shifts (Compositions) to insert to the database
	 * @throws SQLException Error during the insertion
	 */
	public void insertComposition (Connection con, List<Composition> lComposition)
		throws SQLException {

		// TODO Add Composition to database
		PreparedStatement pstmtIns = null;

		if (lComposition != null) {
			String sqlInsert = "INSERT INTO Composades VALUES (?, ?, ?)";
			pstmtIns = con.prepareStatement( sqlInsert );

			for (Composition com: lComposition) {
				pstmtIns.clearParameters();
				pstmtIns.setInt(1,com.getReceiptCode().intValue());
				pstmtIns.setInt(2, com.getIngredientCode().intValue());
				pstmtIns.setDouble(3, com.getQuantity());
			
				pstmtIns.executeUpdate();	
				System.out.println("Insert OK");
			}
			
			pstmtIns.close();
		}		
	}

	
	/**
	 * Returns the appropriate error message according to the
	 * generated exception
	 * @param se DB Exception
	 * @return Error message for the user to see
	 */
	private String processException (SQLException se) {
		// Check if the problems is because that broadcast already existed
		String message = se.getMessage(); 
		
		if (se.getErrorCode() == PK_ERROR)
			return ("ERROR: Composition already exists: " + message);

		// Check if the problem is because of a foreign key violation
		else if (se.getErrorCode() == FK_ERROR) 
		{	 
			if (message != null)
			{
				if (message.indexOf(CONSTRAINT_FK_RECEIPT) != -1)
					return ("ERROR: Receipt does not exist: "+ se.getMessage());
				else if (message.indexOf(CONSTRAINT_FK_INGREDIENT) != -1)
					return ("ERROR: Ingredient does not exist: "+ se.getMessage());			
			}
		//Check if the problem is a rule violation
		}else if (se.getErrorCode() == RULE_ERROR)
				return ("ERROR: Too much calories for a healthy dish: "+ se.getMessage());
		
		// Internal error
		return ("ERROR (" + se.getClass() + "): " + se.getMessage());
	}
	
	
	 /**
	 * Main method.
	 * @param args Method parameters
	 */ 
	public static void main(String[] args) {
		CompositionInsertion com = new CompositionInsertion();
		Connection con = null;

		// TODO Get a connection to the database
		
		boolean error = false;
		
		BDAccessor db = new BDAccessor();
		if ( (con = db.getConnection()) == null) {
			System.exit(-1);
		}


		try {
			List<Composition> lComposition = com.getCompositionData();
			com.insertComposition(con, lComposition); 
			System.out.println("Composition data was added successfully ");
		}
		catch (SQLException sqlEx){
			// When a SQLException is generated, we check the reason 
			// to provide the appropriate message if the problem is a 
			// primary or foreign key violation
			System.out.println(com.processException(sqlEx));
			error = true;
		}
		catch (Exception e) {
			System.out.println("ERROR (" + e.getClass() + "): " + e.getMessage());
			error = true;
		}
		if (error)
		{
			com.rollback(con);
			System.out.println("Composition data could not be added. All Compositions were rolled back.");
		}else
			com.commit(con);

		
		// TODO Close the database connection
		BDAccessor.closeConnection(con);

	}
}
